home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume89
/
unix
/
rcs.09
< prev
next >
Wrap
Internet Message Format
|
1989-11-19
|
90KB
Path: xanth!mcnc!rutgers!sun-barr!newstop!sun!swap!page
From: page%swap@Sun.COM (Bob Page)
Newsgroups: comp.sources.amiga
Subject: v89i224: rcs - revision control system, Part09/14
Message-ID: <128100@sun.Eng.Sun.COM>
Date: 19 Nov 89 09:25:27 GMT
Sender: news@sun.Eng.Sun.COM
Lines: 3216
Approved: page@sun.com
Submitted-by: rsbx@cbmvax.commodore.com (Raymond S. Brand)
Posting-number: Volume 89, Issue 224
Archive-name: unix/rcs.09
# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
# rcs/rcs.rcsfiles/rcsclean.sh,v
# rcs/rcs.rcsfiles/rcsedit.c,v
# rcs/rcs.rcsfiles/rcsfcmp.c,v
# rcs/rcs.rcsfiles/rcsfnms.c,v
# This is archive 9 of a 14-part kit.
# This archive created: Sun Nov 19 01:12:10 1989
if `test ! -d rcs`
then
mkdir rcs
echo "mkdir rcs"
fi
if `test ! -d rcs/rcs.rcsfiles`
then
mkdir rcs/rcs.rcsfiles
echo "mkdir rcs/rcs.rcsfiles"
fi
echo "extracting rcs/rcs.rcsfiles/rcsclean.sh,v"
sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcsclean.sh,v
Xhead 1.5;
Xbranch 1.5.2;
Xaccess ;
Xsymbols amiga_rcs:1.5.2 cbmvax_source:1.5.1 uunet_june89_dist:1.5;
Xlocks ; strict;
Xcomment @# @;
X
X
X1.5
Xdate 86.07.03.13.09.55; author jdl; state Exp;
Xbranches 1.5.1.1 1.5.2.1;
Xnext ;
X
X1.5.1.1
Xdate 89.08.11.01.42.19; author rsbx; state Exp;
Xbranches ;
Xnext ;
X
X1.5.2.1
Xdate 89.10.13.19.20.06; author rsbx; state Exp;
Xbranches ;
Xnext ;
X
X
Xdesc
X@RCS cleanup operation.
X@
X
X
X
X1.5
Xlog
X@checked in with -k by rsbx at 89.08.10.16.18.40.
X@
Xtext
X@#! /bin/sh
X#
X# RCS cleanup operation.
X# $Header: /arthur/src/local/bin/rcs/src/RCS/rcsclean.sh,v 1.5 86/07/03 13:09:55 jdl Exp $
X#
X# This program removes working files which are copies of the latest
X# revision on the default branch of the corresponding RCS files.
X# For each file given, rcsclean performs a co operation for the latest
X# revision on the default branch, and compares
X# the result with the working file. If the two are identical,
X# the working file is deleted.
X#
X# A typical application in a Makefile would be:
X# clean:; rm *.o; rcsclean *.c *.o
X#
X# Limitation: This program doesn't work if given the name of
X# an RCS file rather than the name of the working file.
X
XPATH=/usr/new/bin:/usr/local/bin:/bin:/usr/bin:/usr/ucb
Xexport PATH
Xprogname=$0
Xif [ $# = 0 ] ; then
X echo "usage: $progname file ..."
X echo "removes all working files that are checked in and are unchanged"
X exit 0
Xfi
XTMPFILE=/tmp/rcscl$$.tmp
Xwhile test $# -gt 0 ; do
X if test -f $1 ; then
X co -p -q $1 > $TMPFILE
X if [ $? = 0 ] ; then
X cmp -s $1 $TMPFILE
X if [ $? = 0 ] ; then
X chmod +w $1; rm -f $1; rcs -u -q $1
X fi
X fi
X fi
X shift
Xdone
Xrm -f $TMPFILE
X@
X
X
X1.5.2.1
Xlog
X@Start of Amiga RCS port branch.
X@
Xtext
X@d4 1
Xa4 1
X# $Header: /u/softeng/rsbx/rcs/amiga/RCS.cbmvax/rcsclean.sh,v 1.5.1.1 89/08/11 01:42:19 rsbx Exp Locker: rsbx $
X@
X
X
X1.5.1.1
Xlog
X@Start of cbmvax RCS source branch.
X@
Xtext
X@d4 1
Xa4 1
X# $Header: /u/softeng/rsbx/rcs/rcs.uunet/src/RCS/rcsclean.sh,v 1.5 86/07/03 13:09:55 jdl Exp $
X@
SHAR_EOF
echo "extracting rcs/rcs.rcsfiles/rcsedit.c,v"
sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcsedit.c,v
Xhead 4.8;
Xbranch 4.8.2;
Xaccess ;
Xsymbols amiga_rcs:4.8.2 cbmvax_source:4.8.1 uunet_june89_dist:4.8;
Xlocks ; strict;
Xcomment @ * @;
X
X
X4.8
Xdate 89.05.01.15.12.35; author narten; state Exp;
Xbranches 4.8.1.1 4.8.2.1;
Xnext ;
X
X4.8.1.1
Xdate 89.08.11.01.42.25; author rsbx; state Exp;
Xbranches ;
Xnext ;
X
X4.8.2.1
Xdate 89.10.13.19.18.24; author rsbx; state Exp;
Xbranches ;
Xnext 4.8.2.2;
X
X4.8.2.2
Xdate 89.10.15.15.44.09; author rsbx; state Exp;
Xbranches ;
Xnext 4.8.2.3;
X
X4.8.2.3
Xdate 89.10.16.19.07.14; author rsbx; state Exp;
Xbranches ;
Xnext 4.8.2.4;
X
X4.8.2.4
Xdate 89.10.16.23.42.40; author rsbx; state Exp;
Xbranches ;
Xnext ;
X
X
Xdesc
X@RCS stream editor.
X@
X
X
X
X4.8
Xlog
X@checked in with -k by rsbx at 89.08.10.16.19.26.
X@
Xtext
X@/*
X * RCS stream editor
X */
X#ifndef lint
Xstatic char rcsid[]= "$Id: rcsedit.c,v 4.8 89/05/01 15:12:35 narten Exp $ Purdue CS";
X#endif
X/**********************************************************************************
X * edits the input file according to a
X * script from stdin, generated by diff -n
X * performs keyword expansion
X **********************************************************************************
X */
X
X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Walter Tichy.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X * Report all problems and direct all questions to:
X * rcs-bugs@@cs.purdue.edu
X *
X
X
X
X
X
X
X
X*/
X
X
X/* $Log: rcsedit.c,v $
X * Revision 4.8 89/05/01 15:12:35 narten
X * changed copyright header to reflect current distribution rules
X *
X * Revision 4.7 88/11/08 13:54:14 narten
X * misplaced semicolon caused infinite loop
X *
X * Revision 4.6 88/11/08 12:01:41 narten
X * changes from eggert@@sm.unisys.com (Paul Eggert)
X *
X * Revision 4.6 88/08/09 19:12:45 eggert
X * Shrink stdio code size; allow cc -R.
X *
X * Revision 4.5 87/12/18 11:38:46 narten
X * Changes from the 43. version. Don't know the significance of the
X * first change involving "rewind". Also, additional "lint" cleanup.
X * (Guy Harris)
X *
X * Revision 4.4 87/10/18 10:32:21 narten
X * Updating version numbers. Changes relative to version 1.1 actually
X * relative to 4.1
X *
X * Revision 1.4 87/09/24 13:59:29 narten
X * Sources now pass through lint (if you ignore printf/sprintf/fprintf
X * warnings)
X *
X * Revision 1.3 87/09/15 16:39:39 shepler
X * added an initializatin of the variables editline and linecorr
X * this will be done each time a file is processed.
X * (there was an obscure bug where if co was used to retrieve multiple files
X * it would dump)
X * fix attributed to Roy Morris @@FileNet Corp ...!felix!roy
X *
X * Revision 1.2 87/03/27 14:22:17 jenkins
X * Port to suns
X *
X * Revision 1.1 84/01/23 14:50:20 kcs
X * Initial revision
X *
X * Revision 4.1 83/05/12 13:10:30 wft
X * Added new markers Id and RCSfile; added locker to Header and Id.
X * Overhauled expandline completely() (problem with $01234567890123456789@@).
X * Moved trymatch() and marker table to rcskeys.c.
X *
X * Revision 3.7 83/05/12 13:04:39 wft
X * Added retry to expandline to resume after failed match which ended in $.
X * Fixed truncation problem for $19chars followed by@@@@.
X * Log no longer expands full path of RCS file.
X *
X * Revision 3.6 83/05/11 16:06:30 wft
X * added retry to expandline to resume after failed match which ended in $.
X * Fixed truncation problem for $19chars followed by@@@@.
X *
X * Revision 3.5 82/12/04 13:20:56 wft
X * Added expansion of keyword Locker.
X *
X * Revision 3.4 82/12/03 12:26:54 wft
X * Added line number correction in case editing does not start at the
X * beginning of the file.
X * Changed keyword expansion to always print a space before closing KDELIM;
X * Expansion for Header shortened.
X *
X * Revision 3.3 82/11/14 14:49:30 wft
X * removed Suffix from keyword expansion. Replaced fclose with ffclose.
X * keyreplace() gets log message from delta, not from curlogmsg.
X * fixed expression overflow in while(c=putc(GETC....
X * checked nil printing.
X *
X * Revision 3.2 82/10/18 21:13:39 wft
X * I added checks for write errors during the co process, and renamed
X * expandstring() to xpandstring().
X *
X * Revision 3.1 82/10/13 15:52:55 wft
X * changed type of result of getc() from char to int.
X * made keyword expansion loop in expandline() portable to machines
X * without sign-extension.
X */
X
X
X#include "rcsbase.h"
X
X
Xextern FILE * fopen();
Xextern char * mktempfile();
Xextern char * bindex();
Xextern FILE * finptr, * frewrite;
Xextern int rewriteflag;
Xextern int nextc;
Xextern char * RCSfilename, * workfilename;
Xextern char * bindex();
Xextern char * getfullRCSname();
Xextern enum markers trymatch();
X
X
XFILE * fcopy, * fedit; /* result and edit file descriptors */
Xchar *resultfile; /* result file name */
Xchar * editfile; /* edit file name */
Xint editline; /*line counter in fedit; starts with 1, is always #lines+1 */
Xint linecorr; /*contains #adds - #deletes in each edit run. */
X /*used to correct editline in case file is not rewound after */
X /* applying one delta */
X
Xiniteditfiles(dir)
Xchar * dir;
X/* Function: Initializes resultfile and editfile with temporary filenames
X * in directory dir. Opens resultfile for reading and writing, with fcopy
X * as file descriptor. fedit is set to nil.
X */
X{
X editline = linecorr = 0; /* make sure we start from the beginning*/
X resultfile=mktempfile(dir,TMPFILE1);
X editfile =mktempfile(dir,TMPFILE2);
X fedit=nil;
X if ((fcopy=fopen(resultfile,"w+"))==NULL) {
X faterror("Can't open working file %s",resultfile);
X }
X}
X
X
Xswapeditfiles(tostdout)
X/* Function: swaps resultfile and editfile, assigns fedit=fcopy,
X * rewinds fedit for reading, and opens resultfile for reading and
X * writing, using fcopy. If tostdout, fcopy is set to stdout.
X */
X{ char * tmpptr;
X if(ferror(fcopy))
X faterror("write failed on %s -- file system full?",resultfile);
X fedit=fcopy;
X rewind(fedit);
X editline = 1; linecorr=0;
X tmpptr=editfile; editfile=resultfile; resultfile=tmpptr;
X if (tostdout)
X fcopy=stdout;
X elsif ((fcopy=fopen(resultfile,"w+"))==NULL) {
X faterror("Can't open working file %s",resultfile);
X }
X}
X
X
Xfinishedit(delta)
Xstruct hshentry * delta;
X/* copy the rest of the edit file and close it (if it exists).
X * if delta!=nil, perform keyword substitution at the same time.
X */
X{
X register int c;
X if (fedit!=nil) {
X if (delta!=nil) {
X while (expandline(fedit,fcopy,delta,false,false)) editline++;
X } else {
X while((c=getc(fedit))!=EOF) {
X VOID putc(c,fcopy);
X if (c=='\n') editline++;
X }
X }
X ffclose(fedit);
X }
X}
X
X
Xcopylines(line,delta)
Xregister int line; struct hshentry * delta;
X/* Function: copies input lines editline..line-1 from fedit to fcopy.
X * If delta != nil, keyword expansion is done simultaneously.
X * editline is updated. Rewinds a file only if necessary.
X */
X{
X
X if (editline>line) {
X /* swap files */
X finishedit((struct hshentry *)nil); swapeditfiles(false);
X /* assumes edit only during last pass, from the beginning*/
X }
X while (editline<line) {
X /*copy another line*/
X if (delta)
X VOID expandline(fedit,fcopy,delta,false,false);
X else
X while (putc(getc(fedit),fcopy)!='\n');
X editline++;
X }
X}
X
X
X
Xxpandstring(delta)
Xstruct hshentry * delta;
X/* Function: Reads a string terminated by SDELIM from finptr and writes it
X * to fcopy. Double SDELIM is replaced with single SDELIM.
X * Keyword expansion is performed with data from delta.
X * If rewriteflag==true, the string is also copied unchanged to frewrite.
X * editline is updated.
X */
X{
X editline=1;
X while (expandline(finptr,fcopy,delta,true,rewriteflag)) editline++;
X nextc='\n';
X}
X
X
Xcopystring()
X/* Function: copies a string terminated with a single SDELIM from finptr to
X * fcopy, replacing all double SDELIM with a single SDELIM.
X * If rewriteflag==true, the string also copied unchanged to frewrite.
X * editline is set to (number of lines copied)+1.
X * Assumption: next character read is first string character.
X */
X{ register c;
X register FILE *fin, *frew, *fcop;
X register write;
X
X fin=finptr; frew=frewrite; fcop=fcopy;
X write=rewriteflag;
X editline=1;
X while ((c=GETC(fin,frew,write)) != EOF) {
X if ((c==SDELIM)&&((c=GETC(fin,frew,write)) != SDELIM)){
X /* end of string */
X nextc = c;
X return;
X }
X VOID putc(c,fcop);
X if (c=='\n') editline++;
X }
X nextc = c;
X serror("Unterminated string");
X return;
X}
X
X
X
X
Xeditstring(delta)
Xstruct hshentry * delta;
X/* Function: reads an edit script from finptr and applies it to
X * file fedit; the result is written to fcopy.
X * If delta!=nil, keyword expansion is performed simultaneously.
X * If frewrite==true, the edit script is also copied verbatim to frewrite.
X * Assumes that all these files are open.
X * If running out of lines in fedit, fedit and fcopy are swapped.
X * resultfile and editfile are the names of the files that go with fcopy
X * and fedit, respectively.
X * Assumes the next input character from finptr is the first character of
X * the edit script. Resets nextc on exit.
X */
X{
X int ed; /* editor command */
X register int c;
X register FILE *fin, *frew;
X register int write, i;
X int line, length;
X
X fin=finptr; frew=frewrite;
X editline += linecorr; linecorr=0; /*correct line number*/
X write=rewriteflag;
X for (;;) {
X /* read next command and decode */
X /* assume next non-white character is command name*/
X while((ed=GETC(fin,frew,write))=='\n'||
X ed==' ' || ed=='\t');
X if (ed==SDELIM) break;
X /* now attempt to read numbers. */
X /* fscanf causes trouble because of the required echoing */
X while ((c=GETC(fin,frew,write))==' '); /*skip spaces*/
X if (!('0'<=c && c<='9')) {
X faterror("missing line number in edit script");
X break;
X }
X line= c -'0';
X while ('0'<=(c=GETC(fin,frew,write)) && c<='9') {
X line = line*10 + c-'0';
X }
X while (c==' ') c=GETC(fin,frew,write);
X if (!('0'<=c && c<='9')) {
X faterror("incorrect range in edit script");
X break;
X }
X length= c -'0';
X while ('0'<=(c=GETC(fin,frew,write)) && c<='9') {
X length = length*10 + c-'0';
X }
X while(c!='\n'&&c!=EOF) c=GETC(fin,frew,write); /* skip to end of line */
X
X switch (ed) {
X case 'd':
X copylines(line,delta);
X /* skip over unwanted lines */
X for (i=length;i>0;i--) {
X /*skip next line*/
X while ((c=getc(fedit))!='\n')
X if (c==EOF)
X faterror("EOF during edit");
X editline++;
X }
X linecorr -= length;
X break;
X case 'a':
X copylines(line+1,delta); /*copy only; no delete*/
X for (i=length;i>0;i--) {
X /*copy next line from script*/
X if (delta!=nil)
X VOID expandline(fin,fcopy,delta,true,write);
X else {
X c = GETC(fin,frew,write);
X while (putc(c,fcopy)!='\n'){
X if ((c==SDELIM)&&((c=GETC(fin,frew,write))!=SDELIM)){
X serror("Missing string delimiter in edit script");
X VOID putc(c,fcopy);
X }
X c = GETC(fin,frew,write);
X }
X }
X }
X linecorr += length;
X break;
X default:
X faterror("unknown command in edit script: %c", ed);
X break;
X }
X }
X nextc=GETC(fin,frew,write);
X}
X
X
X
X/* The rest is for keyword expansion */
X
X
X
Xexpandline(in, out, delta,delimstuffed,write)
Xregister FILE * in, * out; struct hshentry * delta;
Xint delimstuffed, write;
X/* Function: Reads a line from in and writes it to out.
X * If delimstuffed==true, double SDELIM is replaced with single SDELIM.
X * Keyword expansion is performed with data from delta.
X * If write==true, the string is also copied unchanged to frewrite.
X * Returns false if end-of-string or end-of-line is detected, true otherwise.
X */
X{
X register c;
X register FILE * frew;
X register w, ds;
X register char * tp;
X char keystring[keylength+2];
X char keyval[keyvallength+2];
X enum markers matchresult;
X
X frew = frewrite;
X w = write;
X ds = delimstuffed;
X c=GETC(in,frew,w);
X for (;;) {
X if (c==EOF) {
X if(ds) {
X error("unterminated string");
X nextc=c;
X }
X return(false);
X }
X
X if (c==SDELIM && ds) {
X if ((c=GETC(in,frew,w))!=SDELIM) {
X /* end of string */
X nextc=c;
X return false;
X }
X }
X VOID putc(c,out);
X
X if (c=='\n') return true; /* end of line */
X
X if (c==KDELIM) {
X /* check for keyword */
X /* first, copy a long enough string into keystring */
X tp=keystring;
X while (((c=GETC(in,frew,w))!=EOF) && (tp<keystring+keylength) && (c!='\n')
X && (c!=SDELIM) && (c!=KDELIM) && (c!=VDELIM)) {
X VOID putc(c,out);
X *tp++ = c;
X }
X *tp++ = c; *tp = '\0';
X matchresult=trymatch(keystring,false);
X if (matchresult==Nomatch) continue;
X /* last c will be dealt with properly by continue*/
X
X /* Now we have a keyword terminated with a K/VDELIM */
X if (c==VDELIM) {
X /* try to find closing KDELIM, and replace value */
X tp=keyval;
X while (((c=GETC(in,frew,w)) != EOF)
X && (c!='\n') && (c!=KDELIM) && (tp<keyval+keyvallength)) {
X *tp++ =c;
X if (c==SDELIM && ds) { /*skip next SDELIM */
X c=GETC(in,frew,w);
X /* Can't be at end of string.
X /* always a \n before closing SDELIM */
X }
X }
X if (c!=KDELIM) {
X /* couldn't find closing KDELIM -- give up */
X VOID putc(VDELIM,out); *tp='\0';
X VOID fputs(keyval,out);
X continue; /* last c handled properly */
X }
X }
X /* now put out the new keyword value */
X keyreplace(matchresult,delta,out);
X }
X c=GETC(in,frew,w);
X } /* end for */
X}
X
X
X
Xkeyreplace(marker,delta,out)
Xenum markers marker; struct hshentry * delta; register FILE * out;
X/* function: ouputs the keyword value(s) corresponding to marker.
X * Attributes are derived from delta.
X */
X{
X char * date;
X register char * sp;
X
X date= delta->date;
X
X switch (marker) {
X case Author:
X VOID fprintf(out,"%c %s %c",VDELIM,delta->author,KDELIM);
X break;
X case Date:
X VOID putc(VDELIM,out);VOID putc(' ',out);
X VOID PRINTDATE(out,date);VOID putc(' ',out);
X VOID PRINTTIME(out,date);VOID putc(' ',out);VOID putc(KDELIM,out);
X break;
X case Id:
X case Header:
X VOID putc(VDELIM,out); VOID putc(' ',out);
X if (marker==Id)
X VOID fputs(bindex(RCSfilename,'/'),out);
X else VOID fputs(getfullRCSname(),out);
X VOID fprintf(out," %s ", delta->num);
X VOID PRINTDATE(out,date);VOID putc(' ',out);VOID PRINTTIME(out,date);
X VOID fprintf(out, " %s %s ",delta->author,delta->state);
X if (delta->lockedby!=nil)
X VOID fprintf(out,"Locker: %s ",delta->lockedby);
X VOID putc(KDELIM,out);
X break;
X case Locker:
X VOID fprintf(out,"%c %s %c", VDELIM,
X delta->lockedby==nil?"":delta->lockedby,KDELIM);
X break;
X case Log:
X VOID fprintf(out, "%c\t%s %c\n%sRevision %s ",
X VDELIM, bindex(RCSfilename,'/'), KDELIM, Comment, delta->num);
X VOID PRINTDATE(out,date);VOID fputs(" ",out);VOID PRINTTIME(out,date);
X VOID fprintf(out, " %s\n%s",delta->author,Comment);
X /* do not include state here because it may change and is not updated*/
X sp = delta->log;
X while (*sp) if (putc(*sp++,out)=='\n') VOID fputs(Comment,out);
X /* Comment is the comment leader */
X break;
X case RCSfile:
X VOID fprintf(out,"%c %s %c",VDELIM,bindex(RCSfilename,'/'),KDELIM);
X break;
X case Revision:
X VOID fprintf(out,"%c %s %c",VDELIM,delta->num,KDELIM);
X break;
X case Source:
X VOID fprintf(out,"%c %s %c",VDELIM,getfullRCSname(),KDELIM);
X break;
X case State:
X VOID fprintf(out,"%c %s %c",VDELIM,delta->state,KDELIM);
X break;
X case Nomatch:
X VOID putc(KDELIM,out);
X break;
X }
X}
X
X
X@
X
X
X4.8.2.1
Xlog
X@Start of Amiga RCS port branch.
X@
Xtext
X@d5 1
Xa5 5
X<<<<<<< rcsedit.c
Xstatic char rcsid[]= "$Id: rcsedit.c,v 4.8.1.1 89/08/11 01:42:25 rsbx Exp Locker: rsbx $ Purdue CS";
X=======
Xstatic char rcsid[]= "$Id: rcsedit.c,v 1.2 89/09/17 13:35:29 rick Exp $ Purdue CS";
X>>>>>>> 1.2
Xa40 11
X<<<<<<< rcsedit.c
X * Revision 4.8.1.1 89/08/11 01:42:25 rsbx
X * Start of cbmvax RCS source branch.
X=======
X * Revision 1.2 89/09/17 13:35:29 rick
X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
X * All changes done with conditional compile (#ifdef AMIGA). This version
X * compiles correctly with Lattice C version 5.02 or later.
X>>>>>>> 1.2
X *
X<<<<<<< rcsedit.c
Xa41 3
X * checked in with -k by rsbx at 89.08.10.16.19.26.
X *
X * Revision 4.8 89/05/01 15:12:35 narten
Xa52 5
X=======
X * Revision 1.2 88/09/03 15:09:56 rick
X * Port to AmigaDos. All done with conditional compiles
X *
X>>>>>>> 1.2
Xa166 2
X if (fedit != NULL)
X fclose(fedit);
X@
X
X
X4.8.2.2
Xlog
X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
Xsources I have here (and are later than the ones Rick used).
X@
Xtext
X@d5 5
Xa9 1
Xstatic char rcsid[]= "$Id: rcsedit.c,v 4.8.2.1 89/10/13 19:18:24 rsbx Exp Locker: rsbx $ Purdue CS";
Xd45 1
Xa45 3
X * Revision 4.8.2.1 89/10/13 19:18:24 rsbx
X * Start of Amiga RCS port branch.
X *
Xd48 6
Xd55 1
Xd71 5
Xd457 1
Xa457 1
X GETC(in,frew,w);
X@
X
X
X4.8.2.3
Xlog
X@Changed file path handling to deal with Amiga file path sematics.
X@
Xtext
X@d5 1
Xa5 1
Xstatic char rcsid[]= "$Id: rcsedit.c,v 4.8.2.2 89/10/15 15:44:09 rsbx Exp $ Purdue CS";
Xa40 4
X * Revision 4.8.2.2 89/10/15 15:44:09 rsbx
X * Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
X * sources I have here (and are later than the ones Rick used).
X *
Xd133 1
Xd138 1
Xd488 1
Xa488 1
X VOID fputs(fnamepart(RCSfilename),out);
Xd503 1
Xa503 1
X VDELIM, fnamepart(RCSfilename), KDELIM, Comment, delta->num);
Xd512 1
Xa512 1
X VOID fprintf(out,"%c %s %c",VDELIM,fnamepart(RCSfilename),KDELIM);
X@
X
X
X4.8.2.4
Xlog
X@Added function return type for fnamepart().
X@
Xtext
X@d5 1
Xa5 1
Xstatic char rcsid[]= "$Id: rcsedit.c,v 4.8.2.3 89/10/16 19:07:14 rsbx Exp $ Purdue CS";
Xa40 3
X * Revision 4.8.2.3 89/10/16 19:07:14 rsbx
X * Changed file path handling to deal with Amiga file path sematics.
X *
Xa135 1
Xextern char * fnamepart();
X@
X
X
X4.8.1.1
Xlog
X@Start of cbmvax RCS source branch.
X@
Xtext
X@a41 3
X * checked in with -k by rsbx at 89.08.10.16.19.26.
X *
X * Revision 4.8 89/05/01 15:12:35 narten
X@
SHAR_EOF
echo "extracting rcs/rcs.rcsfiles/rcsfcmp.c,v"
sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcsfcmp.c,v
Xhead 4.5;
Xbranch 4.5.2;
Xaccess ;
Xsymbols amiga_rcs:4.5.2 cbmvax_source:4.5.1 uunet_june89_dist:4.5;
Xlocks ; strict;
Xcomment @ * @;
X
X
X4.5
Xdate 89.05.01.15.12.42; author narten; state Exp;
Xbranches 4.5.1.1 4.5.2.1;
Xnext ;
X
X4.5.1.1
Xdate 89.08.11.01.42.29; author rsbx; state Exp;
Xbranches ;
Xnext ;
X
X4.5.2.1
Xdate 89.10.13.19.18.28; author rsbx; state Exp;
Xbranches ;
Xnext 4.5.2.2;
X
X4.5.2.2
Xdate 89.10.15.15.44.13; author rsbx; state Exp;
Xbranches ;
Xnext ;
X
X
Xdesc
X@RCS file comparison.
X@
X
X
X
X4.5
Xlog
X@checked in with -k by rsbx at 89.08.10.16.19.42.
X@
Xtext
X@/*
X * RCS file comparison
X */
X#ifndef lint
Xstatic char rcsid[]= "$Id: rcsfcmp.c,v 4.5 89/05/01 15:12:42 narten Exp $ Purdue CS";
X#endif
X/*****************************************************************************
X * rcsfcmp()
X * Testprogram: define FCMPTEST
X *****************************************************************************
X */
X
X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Walter Tichy.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X * Report all problems and direct all questions to:
X * rcs-bugs@@cs.purdue.edu
X *
X
X
X
X
X
X
X
X*/
X
X
X
X
X
X/* $Log: rcsfcmp.c,v $
X * Revision 4.5 89/05/01 15:12:42 narten
X * changed copyright header to reflect current distribution rules
X *
X * Revision 4.4 88/11/08 12:01:33 narten
X * changes from eggert@@sm.unisys.com (Paul Eggert)
X *
X * Revision 4.4 88/08/09 19:12:50 eggert
X * Shrink stdio code size.
X *
X * Revision 4.3 87/12/18 11:40:02 narten
X * lint cleanups (Guy Harris)
X *
X * Revision 4.2 87/10/18 10:33:06 narten
X * updting version number. Changes relative to 1.1 actually relative to
X * 4.1
X *
X * Revision 1.2 87/03/27 14:22:19 jenkins
X * Port to suns
X *
X * Revision 1.1 84/01/23 14:50:23 kcs
X * Initial revision
X *
X * Revision 4.1 83/05/10 16:24:04 wft
X * Marker matching now uses trymatch(). Marker pattern is now
X * checked precisely.
X *
X * Revision 3.1 82/12/04 13:21:40 wft
X * Initial revision.
X *
X */
X
X/*
X#define FCMPTEST
X/* Testprogram; prints out whether two files are identical,
X * except for keywords
X */
X
X#include "rcsbase.h"
Xextern FILE * fopen();
Xextern enum markers trymatch(); /* check for keywords */
X
X
Xrcsfcmp(xfname,uxfname,delta)
Xchar * xfname, *uxfname; struct hshentry *delta;
X/* Function: compares the files xfname and uxfname. Returns true
X * if xfname has the same contents as uxfname, while disregarding
X * keyword values. For the LOG-keyword, rcsfcmp skips the log message
X * given by the parameter delta in xfname. Thus, rcsfcmp returns true
X * if xfname contains the same as uxfname, with the keywords expanded.
X * Implementation: character-by-character comparison until $ is found.
X * If a $ is found, read in the marker keywords; if they are real keywords
X * and identical, read in keyword value. If value is terminated properly,
X * disregard it and optionally skip log message; otherwise, compare value.
X */
X{
X register int xc,uxc;
X char xkeyword[keylength+2], uxkeyword[keylength+2];
X char xkeyval[keyvallength+1], uxkeyval[keyvallength+1];
X register FILE * xfp, * uxfp;
X register char * tp;
X int result;
X enum markers match1,match2;
X
X if ((xfp=fopen(tp=xfname,"r"))==NULL || (uxfp=fopen(tp=uxfname,"r"))==NULL) {
X faterror("Can't open %s\n", tp);
X return false;
X }
X result=false;
X xc=getc(xfp); uxc=getc(uxfp);
X while( xc == uxc) { /* comparison loop */
X if (xc==EOF) { /* finished; everything is the same*/
X result=true;
X break;
X }
X if ( xc!=KDELIM) {
X /* get the next characters */
X xc=getc(xfp); uxc=getc(uxfp);
X } else {
X /* try to get both keywords */
X tp = xkeyword;
X while( (xc=getc(xfp))!=EOF && (tp< xkeyword+keylength) && (xc!='\n')
X && (xc!=KDELIM) && (xc!=VDELIM))
X *tp++ = xc;
X *tp++ = xc; /* add closing K/VDELIM */
X *tp='\0';
X tp = uxkeyword;
X while( (uxc=getc(uxfp))!=EOF && (tp< uxkeyword+keylength) && (uxc!='\n')
X && (uxc!=KDELIM) && (uxc!=VDELIM))
X *tp++ = uxc;
X *tp++ = xc; /* add closing K/VDELIM */
X *tp='\0';
X /* now we have 2 keywords, or something thal looks like it.*/
X match1=trymatch(xkeyword,false);
X match2=trymatch(uxkeyword,false);
X if (match1 != match2) break; /* not identical */
X#ifdef FCMPTEST
X VOID printf("found potential keywords %s and %s\n",xkeyword,uxkeyword);
X#endif
X
X if (match1 == Nomatch) {
X /* not a keyword pattern, but could still be identical */
X if (strcmp(xkeyword,uxkeyword)==0)
X continue;
X else break;
X }
X#ifdef FCMPTEST
X VOID printf("found common keyword %s\n",xkeyword);
X#endif
X tp=xkeyval;
X if (xc==VDELIM) {/* get value */
X while (((xc=getc(xfp))!=KDELIM) && (xc!='\n') && (xc!=EOF) &&
X (tp<xkeyval+keyvallength))
X *tp++ = xc;
X }
X *tp = '\0'; /*xkeyval now filled with value; possibly empty*/
X tp=uxkeyval;
X if (uxc==VDELIM) {/* get value */
X while (((uxc=getc(uxfp))!=KDELIM) && (uxc!='\n') && (uxc!=EOF) &&
X (tp<uxkeyval+keyvallength))
X *tp++ = uxc;
X }
X *tp = '\0'; /*uxkeyval now filled with value; possibly empty*/
X if (xc!=uxc) break; /* not the same */
X if (xc==KDELIM) {
X xc=getc(xfp); uxc=getc(uxfp); /* skip closing KDELIM */
X /* if the keyword is LOG, also skip the log message in xfp*/
X if (match1==Log) {
X /* first, compute the number of line feeds in log msg */
X int lncnt, ccnt;
X lncnt=2; tp=delta->log;
X while(*tp) if(*tp++=='\n') lncnt++;
X while(xc!=EOF) {
X if (xc=='\n')
X if(--lncnt==0) break;
X xc=getc(xfp);
X }
X /* skip last comment leader */
X /* Can't just skip another line here, because there may be */
X /* additional characters on the line (after the Log....$) */
X for (ccnt=strlen(Comment); ccnt>=0; lncnt--) {
X xc=getc(xfp);
X if(xc=='\n') break;
X /* reads to the end of the comment leader or '\n', */
X /* whatever comes first. This is because some editors */
X /* strip off trailing blanks from a leader like " * ". */
X }
X }
X } else {
X /* both end in the same character, but not a KDELIM */
X /* must compare string values.*/
X#ifdef FCMPTEST
X VOID printf("non-terminated keywords %s, potentially different values\n",xkeyword);
X#endif
X if (strcmp(xkeyval,uxkeyval)!=0) break; /*different */
X xc=getc(xfp); uxc=getc(uxfp); /* skip closing char */
X }
X }
X }
X VOID fclose(xfp); VOID fclose(uxfp);
X return result;
X}
X
X
X
X#ifdef FCMPTEST
Xchar * RCSfilename, * workfilename;
X
Xchar * Comment;
X
Xmain(argc, argv)
Xint argc; char *argv[];
X/* first argument: comment leader; 2nd: log message, 3rd: expanded file,
X * 4th: unexpanded file
X */
X{ struct hshentry delta;
X
X cmdid="rcsfcmp";
X Comment=argv[1];
X delta.log=argv[2];
X if (rcsfcmp(argv[3],argv[4],&delta))
X VOID printf("files are the same\n");
X else VOID printf("files are different\n");
X}
X#endif
X@
X
X
X4.5.2.1
Xlog
X@Start of Amiga RCS port branch.
X@
Xtext
X@d5 1
Xa5 5
X<<<<<<< rcsfcmp.c
Xstatic char rcsid[]= "$Id: rcsfcmp.c,v 4.5.1.1 89/08/11 01:42:29 rsbx Exp Locker: rsbx $ Purdue CS";
X=======
Xstatic char rcsid[]= "$Id: rcsfcmp.c,v 1.2 89/09/17 13:42:09 rick Exp $ Purdue CS";
X>>>>>>> 1.2
Xa42 16
X<<<<<<< rcsfcmp.c
X * Revision 4.5.1.1 89/08/11 01:42:29 rsbx
X * Start of cbmvax RCS source branch.
X *
X * Revision 4.5 89/05/01 15:12:42 narten
X * checked in with -k by rsbx at 89.08.10.16.19.42.
X=======
X * Revision 1.2 89/09/17 13:42:09 rick
X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
X * All changes done with condition compile (#ifdef AMIGA). This
X * version compiles correctly with Lattice C version 5.02 or later.
X *
X * Revision 1.1 89/09/17 13:04:37 rick
X * Initial revision
X>>>>>>> 1.2
X *
X@
X
X
X4.5.2.2
Xlog
X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
Xsources I have here (and are later than the ones Rick used).
X@
Xtext
X@d5 5
Xa9 1
Xstatic char rcsid[]= "$Id: rcsfcmp.c,v 4.5.2.1 89/10/13 19:18:28 rsbx Exp Locker: rsbx $ Purdue CS";
Xd47 1
Xa47 3
X * Revision 4.5.2.1 89/10/13 19:18:28 rsbx
X * Start of Amiga RCS port branch.
X *
Xd53 5
Xd59 4
Xd202 1
Xa202 1
X for (ccnt=strlen(Comment); ccnt>=0;) {
X@
X
X
X4.5.1.1
Xlog
X@Start of cbmvax RCS source branch.
X@
Xtext
X@a43 3
X * checked in with -k by rsbx at 89.08.10.16.19.42.
X *
X * Revision 4.5 89/05/01 15:12:42 narten
X@
SHAR_EOF
echo "extracting rcs/rcs.rcsfiles/rcsfnms.c,v"
sed 's/^X//' << \SHAR_EOF > rcs/rcs.rcsfiles/rcsfnms.c,v
Xhead 4.8;
Xbranch 4.8.2;
Xaccess ;
Xsymbols amiga_rcs:4.8.2 cbmvax_source:4.8.1 uunet_june89_dist:4.8;
Xlocks ; strict;
Xcomment @ * @;
X
X
X4.8
Xdate 89.05.01.15.09.41; author narten; state Exp;
Xbranches 4.8.1.1 4.8.2.1;
Xnext ;
X
X4.8.1.1
Xdate 89.08.11.01.42.32; author rsbx; state Exp;
Xbranches ;
Xnext ;
X
X4.8.2.1
Xdate 89.10.13.19.18.32; author rsbx; state Exp;
Xbranches ;
Xnext 4.8.2.2;
X
X4.8.2.2
Xdate 89.10.15.15.44.18; author rsbx; state Exp;
Xbranches ;
Xnext 4.8.2.3;
X
X4.8.2.3
Xdate 89.10.15.18.27.52; author rsbx; state Exp;
Xbranches ;
Xnext 4.8.2.4;
X
X4.8.2.4
Xdate 89.10.16.19.07.19; author rsbx; state Exp;
Xbranches ;
Xnext 4.8.2.5;
X
X4.8.2.5
Xdate 89.10.16.23.54.04; author rsbx; state Exp;
Xbranches ;
Xnext 4.8.2.6;
X
X4.8.2.6
Xdate 89.10.17.16.17.29; author rsbx; state Exp;
Xbranches ;
Xnext 4.8.2.7;
X
X4.8.2.7
Xdate 89.10.17.18.38.55; author rsbx; state Exp;
Xbranches ;
Xnext 4.8.2.8;
X
X4.8.2.8
Xdate 89.10.30.13.44.29; author rsbx; state Exp;
Xbranches ;
Xnext 4.8.2.9;
X
X4.8.2.9
Xdate 89.10.30.13.53.10; author rsbx; state Exp;
Xbranches ;
Xnext 4.8.2.10;
X
X4.8.2.10
Xdate 89.11.01.14.43.14; author rsbx; state Exp;
Xbranches ;
Xnext 4.8.2.11;
X
X4.8.2.11
Xdate 89.11.05.18.03.59; author rsbx; state Exp;
Xbranches ;
Xnext ;
X
X
Xdesc
X@RCS file name handling.
X@
X
X
X
X4.8
Xlog
X@checked in with -k by rsbx at 89.08.10.16.20.00.
X@
Xtext
X@/*
X * RCS file name handling
X */
X#ifndef lint
X static char
X rcsid[]= "$Id: rcsfnms.c,v 4.8 89/05/01 15:09:41 narten Exp $ Purdue CS";
X#endif
X/****************************************************************************
X * creation and deletion of semaphorefile,
X * creation of temporary filenames and cleanup()
X * pairing of RCS file names and working file names.
X * Testprogram: define PAIRTEST
X ****************************************************************************
X */
X
X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Walter Tichy.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X * Report all problems and direct all questions to:
X * rcs-bugs@@cs.purdue.edu
X *
X
X
X
X
X
X
X
X*/
X
X
X
X
X/* $Log: rcsfnms.c,v $
X * Revision 4.8 89/05/01 15:09:41 narten
X * changed getwd to not stat empty directories.
X *
X * Revision 4.7 88/11/08 12:01:22 narten
X * changes from eggert@@sm.unisys.com (Paul Eggert)
X *
X * Revision 4.7 88/08/09 19:12:53 eggert
X * Fix troff macro comment leader bug; add Prolog; allow cc -R; remove lint.
X *
X * Revision 4.6 87/12/18 11:40:23 narten
X * additional file types added from 4.3 BSD version, and SPARC assembler
X * comment character added. Also, more lint cleanups. (Guy Harris)
X *
X * Revision 4.5 87/10/18 10:34:16 narten
X * Updating version numbers. Changes relative to 1.1 actually relative
X * to verion 4.3
X *
X * Revision 1.3 87/03/27 14:22:21 jenkins
X * Port to suns
X *
X * Revision 1.2 85/06/26 07:34:28 svb
X * Comment leader '% ' for '*.tex' files added.
X *
X * Revision 1.1 84/01/23 14:50:24 kcs
X * Initial revision
X *
X * Revision 4.3 83/12/15 12:26:48 wft
X * Added check for KDELIM in file names to pairfilenames().
X *
X * Revision 4.2 83/12/02 22:47:45 wft
X * Added csh, red, and sl file name suffixes.
X *
X * Revision 4.1 83/05/11 16:23:39 wft
X * Added initialization of Dbranch to InitAdmin(). Canged pairfilenames():
X * 1. added copying of path from workfile to RCS file, if RCS file is omitted;
X * 2. added getting the file status of RCS and working files;
X * 3. added ignoring of directories.
X *
X * Revision 3.7 83/05/11 15:01:58 wft
X * Added comtable[] which pairs file name suffixes with comment leaders;
X * updated InitAdmin() accordingly.
X *
X * Revision 3.6 83/04/05 14:47:36 wft
X * fixed Suffix in InitAdmin().
X *
X * Revision 3.5 83/01/17 18:01:04 wft
X * Added getwd() and rename(); these can be removed by defining
X * V4_2BSD, since they are not needed in 4.2 bsd.
X * Changed sys/param.h to sys/types.h.
X *
X * Revision 3.4 82/12/08 21:55:20 wft
X * removed unused variable.
X *
X * Revision 3.3 82/11/28 20:31:37 wft
X * Changed mktempfile() to store the generated file names.
X * Changed getfullRCSname() to store the file and pathname, and to
X * delete leading "../" and "./".
X *
X * Revision 3.2 82/11/12 14:29:40 wft
X * changed pairfilenames() to handle file.sfx,v; also deleted checkpathnosfx(),
X * checksuffix(), checkfullpath(). Semaphore name generation updated.
X * mktempfile() now checks for nil path; freefilename initialized properly.
X * Added Suffix .h to InitAdmin. Added testprogram PAIRTEST.
X * Moved rmsema, trysema, trydiraccess, getfullRCSname from rcsutil.c to here.
X *
X * Revision 3.1 82/10/18 14:51:28 wft
X * InitAdmin() now initializes StrictLocks=STRICT_LOCKING (def. in rcsbase.h).
X * renamed checkpath() to checkfullpath().
X */
X
X
X#include "rcsbase.h"
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/dir.h>
X
Xextern char * rindex();
Xextern char * mktemp();
Xextern FILE * fopen();
Xextern char * getwd(); /* get working directory; forward decl */
Xextern int stat(), fstat();
X
Xextern FILE * finptr; /* RCS input file descriptor */
Xextern FILE * frewrite; /* New RCS file descriptor */
Xextern char * RCSfilename, * workfilename; /* filenames */
Xstruct stat RCSstat, workstat; /* file status for RCS file and working file */
Xint haveRCSstat, haveworkstat; /* indicators if status availalble */
X
X
Xchar tempfilename [NCPFN+10]; /* used for derived file names */
Xchar sub1filename [NCPPN]; /* used for files path/file.sfx,v */
Xchar sub2filename [NCPPN]; /* used for files path/RCS/file.sfx,v */
Xchar semafilename [NCPPN]; /* name of semaphore file */
Xint madesema; /* indicates whether a semaphore file has been set */
Xchar * tfnames[10]; /* temp. file names to be unlinked when finished */
Xint freefilename; /* index of next free file name in tfnames[] */
X
X
Xstruct compair {
X char * suffix, * comlead;
X};
X
Xstruct compair comtable[] = {
X/* comtable pairs each filename suffix with a comment leader. The comment */
X/* leader is placed before each line generated by the $Log keyword. This */
X/* table is used to guess the proper comment leader from the working file's */
X/* suffix during initial ci (see InitAdmin()). Comment leaders are needed */
X/* for languages without multiline comments; for others they are optional. */
X "c", " * ", /* C */
X "csh", "# ", /* shell */
X "e", "# ", /* efl */
X "f", "c ", /* fortran */
X "h", " * ", /* C-header */
X "l", " * ", /* lex NOTE: conflict between lex and franzlisp*/
X "mac", "; ", /* macro vms or dec-20 or pdp-11 macro */
X "me", ".\\\" ",/* me-macros t/nroff*/
X "mm", ".\\\" ",/* mm-macros t/nroff*/
X "ms", ".\\\" ",/* ms-macros t/nroff*/
X "p", " * ", /* pascal */
X "pl", "% ", /* prolog */
X "r", "# ", /* ratfor */
X "red", "% ", /* psl/rlisp */
X
X#ifdef sparc
X "s", "! ", /* assembler */
X#endif
X#ifdef mc68000
X "s", "| ", /* assembler */
X#endif
X#ifdef pdp11
X "s", "/ ", /* assembler */
X#endif
X#ifdef vax
X "s", "# ", /* assembler */
X#endif
X
X "sh", "# ", /* shell */
X "sl", "% ", /* psl */
X "red", "% ", /* psl/rlisp */
X "cl", ";;; ", /* common lisp */
X "ml", "; ", /* mocklisp */
X "el", "; ", /* gnulisp */
X "tex", "% ", /* tex */
X "y", " * ", /* yacc */
X "ye", " * ", /* yacc-efl */
X "yr", " * ", /* yacc-ratfor */
X "", "# ", /* default for empty suffix */
X nil, "" /* default for unknown suffix; must always be last */
X};
X
X
Xffclose(fptr)
XFILE * fptr;
X/* Function: checks ferror(fptr) and aborts the program if there were
X * errors; otherwise closes fptr.
X */
X{ if (ferror(fptr) || fclose(fptr)==EOF)
X faterror("File read or write error; file system full?");
X}
X
X
X
Xint trysema(RCSname,makesema)
Xchar * RCSname; int makesema;
X/* Function: Checks whether a semaphore file exists for RCSname. If yes,
X * returns false. If not, creates one if makesema==true and returns true
X * if successful. If a semaphore file was created, madesema is set to true.
X * The name of the semaphore file is put into variable semafilename.
X */
X{
X register char * tp, *sp, *lp;
X int fdesc;
X
X sp=RCSname;
X lp = rindex(sp,'/');
X if (lp==0) {
X semafilename[0]='.'; semafilename[1]='/';
X tp= &semafilename[2];
X } else {
X /* copy path */
X tp=semafilename;
X do *tp++ = *sp++; while (sp<=lp);
X }
X /*now insert `,' and append file name */
X *tp++ = ',';
X lp = rindex(sp, RCSSEP);
X while (sp<lp) *tp++ = *sp++;
X *tp++ = ','; *tp++ = '\0'; /* will be the same length as RCSname*/
X
X madesema = false;
X if (access(semafilename, 0) == 0) {
X error("RCS file %s is in use",RCSname);
X return false;
X }
X if (makesema) {
X if ((fdesc=creat(semafilename, 000)) == -1) {
X error("Can't create semaphore file for RCS file %s",RCSname);
X return false;
X } else
X VOID close(fdesc);
X madesema=true;
X }
X return true;
X}
X
X
Xrmsema()
X/* Function: delete the semaphore file if madeseam==true;
X * sets madesema to false.
X */
X{
X if (madesema) {
X madesema=false;
X if (unlink(semafilename) == -1) {
X error("Can't find semaphore file %s",semafilename);
X }
X }
X}
X
X
X
XInitCleanup()
X{ freefilename = 0; /* initialize pointer */
X}
X
X
Xcleanup()
X/* Function: closes input file and rewrite file.
X * Unlinks files in tfnames[], deletes semaphore file.
X */
X{
X register int i;
X
X if (finptr!=NULL) VOID fclose(finptr);
X if (frewrite!=NULL) VOID fclose(frewrite);
X for (i=0; i<freefilename; i++) {
X if (tfnames[i][0]!='\0') VOID unlink(tfnames[i]);
X }
X InitCleanup();
X rmsema();
X}
X
X
Xchar * mktempfile(fullpath,filename)
Xregister char * fullpath, * filename;
X/* Function: Creates a unique filename using the process id and stores it
X * into a free slot in tfnames. The filename consists of the path contained
X * in fullpath concatenated with filename. filename should end in "XXXXXX".
X * Because of storage in tfnames, cleanup() can unlink the file later.
X * freefilename indicates the lowest unoccupied slot in tfnames.
X * Returns a pointer to the filename created.
X * Example use: mktempfile("/tmp/", somefilename)
X */
X{
X register char * lastslash, *tp;
X if ((tp=tfnames[freefilename])==nil)
X tp=tfnames[freefilename] = talloc(NCPPN);
X if (fullpath!=nil && (lastslash=rindex(fullpath,'/'))!=0) {
X /* copy path */
X while (fullpath<=lastslash) *tp++ = *fullpath++;
X }
X while (*tp++ = *filename++);
X return (mktemp(tfnames[freefilename++]));
X}
X
X
X
X
Xchar * bindex(sp,c)
Xregister char * sp, c;
X/* Function: Finds the last occurrence of character c in string sp
X * and returns a pointer to the character just beyond it. If the
X * character doesn't occur in the string, sp is returned.
X */
X{ register char * r;
X r = sp;
X while (*sp) {
X if (*sp++ == c) r=sp;
X }
X return r;
X}
X
X
X
X
X
XInitAdmin()
X/* function: initializes an admin node */
X{ register char * Suffix;
X register int i;
X
X Head=Dbranch=nil; AccessList=nil; Symbols=nil; Locks=nil;
X StrictLocks=STRICT_LOCKING;
X
X /* guess the comment leader from the suffix*/
X Suffix=bindex(workfilename, '.');
X if (Suffix==workfilename) Suffix= ""; /* empty suffix; will get default*/
X for (i=0;;i++) {
X if (comtable[i].suffix==nil) {
X Comment=comtable[i].comlead; /*default*/
X break;
X } elsif (strcmp(Suffix,comtable[i].suffix)==0) {
X Comment=comtable[i].comlead; /*default*/
X break;
X }
X }
X Lexinit(); /* Note: if finptr==NULL, reads nothing; only initializes*/
X}
X
X
X
Xchar * findpairfile(argc, argv, fname)
Xint argc; char * argv[], *fname;
X/* Function: Given a filename fname, findpairfile scans argv for a pathname
X * ending in fname. If found, returns a pointer to the pathname, and sets
X * the corresponding pointer in argv to nil. Otherwise returns fname.
X * argc indicates the number of entries in argv. Some of them may be nil.
X */
X{
X register char * * next, * match;
X register int count;
X
X for (next = argv, count = argc; count>0; next++,count--) {
X if ((*next != nil) && strcmp(bindex(*next,'/'),fname)==0) {
X /* bindex finds the beginning of the file name stem */
X match= *next;
X *next=nil;
X return match;
X }
X }
X return fname;
X}
X
X
Xint pairfilenames(argc, argv, mustread, tostdout)
Xint argc; char ** argv; int mustread, tostdout;
X/* Function: Pairs the filenames pointed to by argv; argc indicates
X * how many there are.
X * Places a pointer to the RCS filename into RCSfilename,
X * and a pointer to the name of the working file into workfilename.
X * If both the workfilename and the RCS filename are given, and tostdout
X * is true, a warning is printed.
X *
X * If the working file exists, places its status into workstat and
X * sets haveworkstat to 0; otherwise, haveworkstat is set to -1;
X * Similarly for the RCS file and the variables RCSstat and haveRCSstat.
X *
X * If the RCS file exists, it is opened for reading, the file pointer
X * is placed into finptr, and the admin-node is read in; returns 1.
X * If the RCS file does not exist and mustread==true, an error is printed
X * and 0 returned.
X * If the RCS file does not exist and mustread==false, the admin node
X * is initialized to empty (Head, AccessList, Locks, Symbols, StrictLocks, Dbranch)
X * and -1 returned.
X *
X * 0 is returned on all errors. Files that are directories are errors.
X * Also calls InitCleanup();
X */
X{
X register char * sp, * tp;
X char * lastsep, * purefname, * pureRCSname;
X int opened, returncode;
X char * RCS1;
X char prefdir[NCPPN];
X
X if (*argv == nil) return 0; /* already paired filename */
X if (rindex(*argv,KDELIM)!=0) {
X /* KDELIM causes havoc in keyword expansion */
X error("RCS file name may not contain %c",KDELIM);
X return 0;
X }
X InitCleanup();
X
X /* first check suffix to see whether it is an RCS file or not */
X purefname=bindex(*argv, '/'); /* skip path */
X lastsep=rindex(purefname, RCSSEP);
X if (lastsep!= 0 && *(lastsep+1)==RCSSUF && *(lastsep+2)=='\0') {
X /* RCS file name given*/
X RCS1=(*argv); pureRCSname=purefname;
X /* derive workfilename*/
X sp = purefname; tp=tempfilename;
X while (sp<lastsep) *tp++ = *sp++; *tp='\0';
X /* try to find workfile name among arguments */
X workfilename=findpairfile(argc-1,argv+1,tempfilename);
X if (strlen(pureRCSname)>NCPFN) {
X error("RCS file name %s too long",RCS1);
X return 0;
X }
X } else {
X /* working file given; now try to find RCS file */
X workfilename= *argv;
X /* derive RCS file name*/
X sp=purefname; tp=tempfilename;
X while (*tp++ = *sp++);
X *(tp-1)=RCSSEP; *tp++=RCSSUF; *tp++='\0';
X /* Try to find RCS file name among arguments*/
X RCS1=findpairfile(argc-1,argv+1,tempfilename);
X pureRCSname=bindex(RCS1, '/');
X if (strlen(pureRCSname)>NCPFN) {
X error("working file name %s too long",workfilename);
X return 0;
X }
X }
X /* now we have a (tentative) RCS filename in RCS1 and workfilename */
X /* First, get status of workfilename */
X haveworkstat=stat(workfilename, &workstat);
X if ((haveworkstat==0) && ((workstat.st_mode & S_IFDIR) == S_IFDIR)) {
X diagnose("Directory %s ignored",workfilename);
X return 0;
X }
X /* Second, try to find the right RCS file */
X if (pureRCSname!=RCS1) {
X /* a path for RCSfile is given; single RCS file to look for */
X finptr=fopen(RCSfilename=RCS1, "r");
X if (finptr!=NULL) {
X returncode=1;
X } else { /* could not open */
X if (access(RCSfilename,0)==0) {
X error("Can't open existing %s", RCSfilename);
X return 0;
X }
X if (mustread) {
X error("Can't find %s", RCSfilename);
X return 0;
X } else {
X /* initialize if not mustread */
X returncode = -1;
X }
X }
X } else {
X /* no path for RCS file name. Prefix it with path of work */
X /* file if RCS file omitted. Make a second name including */
X /* RCSDIR and try to open that one first. */
X sub1filename[0]=sub2filename[0]= '\0';
X if (RCS1==tempfilename) {
X /* RCS file name not given; prepend work path */
X sp= *argv; tp= sub1filename;
X while (sp<purefname) *tp++ = *sp ++;
X *tp='\0';
X VOID strcpy(sub2filename,sub1filename); /* second one */
X }
X VOID strcat(sub1filename,RCSDIR);
X VOID strcpy(prefdir,sub1filename); /* preferred directory for RCS file*/
X VOID strcat(sub1filename,RCS1); VOID strcat(sub2filename,RCS1);
X
X
X opened=(
X ((finptr=fopen(RCSfilename=sub1filename, "r"))!=NULL) ||
X ((finptr=fopen(RCSfilename=sub2filename,"r"))!=NULL) );
X
X if (opened) {
X /* open succeeded */
X returncode=1;
X } else {
X /* open failed; may be read protected */
X if ((access(RCSfilename=sub1filename,0)==0) ||
X (access(RCSfilename=sub2filename,0)==0)) {
X error("Can't open existing %s",RCSfilename);
X return 0;
X }
X if (mustread) {
X error("Can't find %s nor %s",sub1filename,sub2filename);
X return 0;
X } else {
X /* initialize new file. Put into ./RCS if possible, strip off suffix*/
X RCSfilename= (access(prefdir,0)==0)?sub1filename:sub2filename;
X returncode= -1;
X }
X }
X }
X
X if (returncode == 1) { /* RCS file open */
X haveRCSstat=fstat(fileno(finptr),&RCSstat);
X if ((haveRCSstat== 0) && ((RCSstat.st_mode & S_IFDIR) == S_IFDIR)) {
X diagnose("Directory %s ignored",RCSfilename);
X return 0;
X }
X Lexinit(); getadmin();
X } else { /* returncode == -1; RCS file nonexisting */
X haveRCSstat = -1;
X InitAdmin();
X };
X
X if (tostdout&&
X !(RCS1==tempfilename||workfilename==tempfilename))
X /*The last term determines whether a pair of */
X /* file names was given in the argument list */
X warn("Option -p is set; ignoring output file %s",workfilename);
X
X return returncode;
X}
X
X
Xchar * getfullRCSname()
X/* Function: returns a pointer to the full path name of the RCS file.
X * Calls getwd(), but only once.
X * removes leading "../" and "./".
X */
X{ static char pathbuf[NCPPN];
X static char namebuf[NCPPN];
X static int pathlength;
X
X register char * realname, * lastpathchar;
X register int dotdotcounter, realpathlength;
X
X if (*RCSfilename=='/') {
X return(RCSfilename);
X } else {
X if (pathlength==0) { /*call curdir for the first time*/
X if (getwd(pathbuf)==NULL)
X faterror("Can't build current directory path");
X pathlength=strlen(pathbuf);
X if (!((pathlength==1) && (pathbuf[0]=='/'))) {
X pathbuf[pathlength++]='/';
X /* Check needed because some getwd implementations */
X /* generate "/" for the root. */
X }
X }
X /*the following must be redone since RCSfilename may change*/
X /* find how many ../ to remvove from RCSfilename */
X dotdotcounter =0;
X realname = RCSfilename;
X while( realname[0]=='.' &&
X (realname[1]=='/'||(realname[1]=='.'&&realname[2]=='/'))){
X if (realname[1]=='/') {
X /* drop leading ./ */
X realname += 2;
X } else {
X /* drop leading ../ and remember */
X dotdotcounter++;
X realname += 3;
X }
X }
X /* now remove dotdotcounter trailing directories from pathbuf*/
X lastpathchar=pathbuf + pathlength-1;
X while (dotdotcounter>0 && lastpathchar>pathbuf) {
X /* move pointer backwards over trailing directory */
X lastpathchar--;
X if (*lastpathchar=='/') {
X dotdotcounter--;
X }
X }
X if (dotdotcounter>0) {
X error("Can't generate full path name for RCS file");
X return RCSfilename;
X } else {
X /* build full path name */
X realpathlength=lastpathchar-pathbuf+1;
X VOID strncpy(namebuf,pathbuf,realpathlength);
X VOID strcpy(&namebuf[realpathlength],realname);
X return(namebuf);
X }
X }
X}
X
X
X
Xint trydiraccess(filename)
Xchar * filename;
X/* checks write permission in directory of filename and returns
X * true if writable, false otherwise
X */
X{
X char pathname[NCPPN];
X register char * tp, *sp, *lp;
X lp = rindex(filename,'/');
X if (lp==0) {
X /* check current directory */
X if (access(".",2)==0)
X return true;
X else {
X error("Current directory not writable");
X return false;
X }
X }
X /* copy path */
X sp=filename;
X tp=pathname;
X do *tp++ = *sp++; while (sp<=lp);
X *tp='\0';
X if (access(pathname,2)==0)
X return true;
X else {
X error("Directory %s not writable", pathname);
X return false;
X }
X}
X
X
X
X#ifndef V4_2BSD
X/* rename() and getwd() will be provided in bsd 4.2 */
X
X
Xint rename(from, to)
Xchar * from, *to;
X/* Function: renames a file with the name given by from to the name given by to.
X * unlinks the to-file if it already exists. returns -1 on error, 0 otherwise.
X */
X{ VOID unlink(to); /* no need to check return code; will be caught by link*/
X /* no harm done if file "to" does not exist */
X if (link(from,to)<0) return -1;
X return(unlink(from));
X}
X
X
X
X#define dot "."
X#define dotdot ".."
X
X
X
Xchar * getwd(name)
Xchar * name;
X/* Function: places full pathname of current working directory into name and
X * returns name on success, NULL on failure.
X * getwd is an adaptation of pwd. May not return to the current directory on
X * failure.
X */
X{
X FILE *file;
X struct stat d, dd;
X char buf[2]; /* to NUL-terminate dir.d_name */
X struct direct dir;
X
X int rdev, rino;
X int off;
X register i,j;
X
X name[off= 0] = '/';
X name[1] = '\0';
X buf[0] = '\0';
X if (stat("/", &d)<0) return NULL;
X rdev = d.st_dev;
X rino = d.st_ino;
X for (;;) {
X if (stat(dot, &d)<0) return NULL;
X if (d.st_ino==rino && d.st_dev==rdev) {
X if (name[off] == '/') name[off] = '\0';
X chdir(name); /*change back to current directory*/
X return name;
X }
X if ((file = fopen(dotdot,"r")) == NULL) return NULL;
X if (fstat(fileno(file), &dd)<0) goto fail;
X chdir(dotdot);
X if(d.st_dev == dd.st_dev) {
X if(d.st_ino == dd.st_ino) {
X if (name[off] == '/') name[off] = '\0';
X chdir(name); /*change back to current directory*/
X VOID fclose(file);
X return name;
X }
X do {
X if (fread((char *)&dir, sizeof(dir), 1, file) !=1)
X goto fail;
X } while (dir.d_ino != d.st_ino);
X }
X else do {
X if(fread((char *)&dir, sizeof(dir), 1, file) != 1) {
X goto fail;
X }
X if (dir.d_ino == 0)
X dd.st_ino = d.st_ino + 1;
X else if (stat(dir.d_name, &dd) < 0)
X goto fail;
X } while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev);
X VOID fclose(file);
X
X /* concatenate file name */
X i = -1;
X while (dir.d_name[++i] != 0);
X for(j=off+1; j>0; --j)
X name[j+i+1] = name[j];
X off=i+off+1;
X name[i+1] = '/';
X for(--i; i>=0; --i)
X name[i+1] = dir.d_name[i];
X } /* end for */
X
Xfail: VOID fclose(file);
X return NULL;
X}
X
X
X#endif
X
X
X#ifdef PAIRTEST
X/* test program for pairfilenames() and getfullRCSname() */
Xchar * workfilename, *RCSfilename;
Xextern int quietflag;
X
Xmain(argc, argv)
Xint argc; char *argv[];
X{
X int result;
X int initflag,tostdout;
X quietflag=tostdout=initflag=false;
X cmdid="pair";
X
X while(--argc, ++argv, argc>=1 && ((*argv)[0] == '-')) {
X switch ((*argv)[1]) {
X
X case 'p': tostdout=true;
X break;
X case 'i': initflag=true;
X break;
X case 'q': quietflag=true;
X break;
X default: error("unknown option: %s", *argv);
X break;
X }
X }
X
X do {
X RCSfilename=workfilename=nil;
X result=pairfilenames(argc,argv,!initflag,tostdout);
X if (result!=0) {
X diagnose("RCSfile: %s; working file: %s",RCSfilename,workfilename);
X diagnose("Full RCS file name: %s", getfullRCSname());
X }
X switch (result) {
X case 0: continue; /* already paired file */
X
X case 1: if (initflag) {
X error("RCS file %s exists already",RCSfilename);
X } else {
X diagnose("RCS file %s exists",RCSfilename);
X }
X VOID fclose(finptr);
X break;
X
X case -1:diagnose("RCS file does not exist");
X break;
X }
X
X } while (++argv, --argc>=1);
X
X}
X#endif
X@
X
X
X4.8.2.1
Xlog
X@Start of Amiga RCS port branch.
X@
Xtext
X@d6 1
Xa6 5
X<<<<<<< rcsfnms.c
X rcsid[]= "$Id: rcsfnms.c,v 4.8.1.1 89/08/11 01:42:32 rsbx Exp Locker: rsbx $ Purdue CS";
X=======
X rcsid[]= "$Id: rcsfnms.c,v 1.2 89/09/17 13:35:38 rick Exp $ Purdue CS";
X>>>>>>> 1.2
Xa44 11
X<<<<<<< rcsfnms.c
X * Revision 4.8.1.1 89/08/11 01:42:32 rsbx
X * Start of cbmvax RCS source branch.
X=======
X * Revision 1.2 89/09/17 13:35:38 rick
X * Port to AmigaDos done by Rick Schaeffer (ricks@@iscuva.iscs.com)
X * All changes done with conditional compile (#ifdef AMIGA). This version
X * compiles correctly with Lattice C version 5.02 or later.
X>>>>>>> 1.2
X *
X<<<<<<< rcsfnms.c
Xa45 3
X * checked in with -k by rsbx at 89.08.10.16.20.00.
X *
X * Revision 4.8 89/05/01 15:09:41 narten
Xa53 8
X=======
X * Revision 1.3 89/09/16 09:43:16 rick
X * Modified AMIGA changes to work with Lattice C
X *
X * Revision 1.2 88/09/03 15:10:24 rick
X * Port to AmigaDos. All done with conditional compiles
X *
X>>>>>>> 1.2
Xd115 2
Xa116 3
X#ifdef AMIGA
X#include "stat.h"
X#else
Xa119 2
X#endif
X#include "rcsbase.h"
Xa120 2
Xextern int errno;
X
Xd201 1
Xa201 9
X{
X if (fptr == NULL)
X return;
X#ifdef AMIGA
X if (ferror(fptr))
X warn("File read or write error %d; file system full?",errno);
X fclose(fptr);
X#else
X if (ferror(fptr) || (fclose(fptr)==EOF))
Xa202 1
X#endif
Xa220 3
X#ifdef AMIGA
X tp = &semafilename[0];
X#else
Xa222 1
X#endif
Xa299 1
X<<<<<<< rcsfnms.c
Xa301 14
X=======
X lastfilename++;
X if ((tp=tfnames[lastfilename])==nil)
X tp=tfnames[lastfilename] = malloc(NCPPN);
X#ifdef AMIGA
X *tp = 0;
X if (fullpath!=nil) {
X if ((lastslash=rindex(fullpath,'/')) == NULL)
X lastslash = rindex(fullpath,':');
X if (lastslash != NULL)
X while (fullpath<=lastslash) *tp++ = *fullpath++;
X }
X#else
X>>>>>>> 1.2
Xa305 1
X#endif
Xa450 1
X#ifndef AMIGA
Xa454 1
X#endif
Xa516 1
X#ifndef AMIGA
Xa521 1
X#endif
Xa612 3
X#ifdef AMIGA
X return true;
X#else
Xa618 1
X#endif
Xd638 1
Xa638 1
X#ifndef AMIGA
Xa648 1
X#endif
Xa649 3
X#ifdef AMIGA
X#include <libraries/dosextens.h>
X#include <exec/memory.h>
Xa650 3
Xextern struct Process *FindTask();
Xextern struct FileLock *ParentDir(), *Lock();
Xextern char *AllocMem();
Xa651 51
Xchar *followpath(lock,level)
Xstruct FileLock *lock;
Xint level;
X{
X struct FileInfoBlock *fib;
X struct FileLock *newlock;
X static char pathbuf[NCPPN];
X
X if (! lock)
X return(pathbuf);
X if (level == 0)
X pathbuf[0] = 0;
X fib = (struct FileInfoBlock *) AllocMem((long)sizeof(struct FileInfoBlock),MEMF_CLEAR);
X if (fib == NULL) {
X printf("followpath: Out of Memory\n");
X return(pathbuf);
X }
X newlock = ParentDir(lock);
X followpath(newlock,1);
X if (Examine(lock,fib)) {
X if (fib->fib_FileName[0] > ' ')
X strcat(pathbuf,fib->fib_FileName);
X else
X strcat(pathbuf,"RAM");
X if (newlock == NULL)
X strcat(pathbuf,":");
X else
X strcat(pathbuf,"/");
X }
X UnLock(lock);
X if (fib)
X FreeMem(fib,(long) sizeof(struct FileInfoBlock));
X return(pathbuf);
X}
X
Xchar *getwd(name)
Xchar *name;
X{
X struct FileLock *oldlock;
X
X oldlock = Lock("",ACCESS_READ);
X if (oldlock == NULL)
X return(NULL);
X strcpy(name,followpath(oldlock,0));
X if (name[strlen(name)-1] == '/')
X name[strlen(name)-1] = 0;
X return(name);
X}
X
X#else
X
Xa727 1
X#endif
Xa782 33
X}
X#endif
X
X#ifdef AMIGA
Xchar *mktemp(template)
Xchar *template;
X{
X register char *cp;
X register unsigned long val;
X
X cp = template;
X cp += strlen(cp);
X for (val = (unsigned long) FindTask(0L) ; ; )
X if (*--cp == 'X') {
X *cp = val%10 + '0';
X val /= 10;
X } else if (*cp != '.')
X break;
X
X if (*++cp != 0) {
X *cp = 'A';
X while (access(template, 0) == 0) {
X if (*cp == 'Z') {
X *template = 0;
X break;
X }
X ++*cp;
X }
X } else {
X if (access(template, 0) == 0)
X *template = 0;
X }
X return template;
X@
X
X
X4.8.2.2
Xlog
X@Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
Xsources I have here (and are later than the ones Rick used).
X@
Xtext
X@d6 5
Xa10 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.1 89/10/13 19:18:32 rsbx Exp Locker: rsbx $ Purdue CS";
Xd49 1
Xa49 3
X * Revision 4.8.2.1 89/10/13 19:18:32 rsbx
X * Start of Amiga RCS port branch.
X *
Xd52 6
Xd59 1
Xd72 8
Xd276 1
Xa276 1
X *tp++ = ','; *tp = '\0'; /* will be the same length as RCSname*/
Xd344 1
Xd347 4
Xd360 1
Xd499 1
Xa499 1
X *(tp-1)=RCSSEP; *tp++=RCSSUF; *tp='\0';
Xa719 1
X#ifdef RICKS
Xa774 10
X#else
Xchar *getwd(char *name)
X {
X if (getcd(0, name) == 0)
X {
X return name;
X }
X return NULL;
X }
X#endif RICKS
X@
X
X
X4.8.2.3
Xlog
X@More changes to make Amiga port work.
X@
Xtext
X@d6 1
Xa6 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.2 89/10/15 15:44:18 rsbx Exp $ Purdue CS";
Xa44 4
X * Revision 4.8.2.2 89/10/15 15:44:18 rsbx
X * Finished the integration of Rick Schaeffer's RCS Amiga port with the RCS
X * sources I have here (and are later than the ones Rick used).
X *
Xd245 1
Xa245 1
X tp = &semafilename[0];
Xa260 5
X#ifdef DEBUG
X fprintf(stderr,"semafilename = %%%s%%\n", semafilename);
X fflush(stderr);
X#endif
X
Xd529 1
Xd549 1
Xa549 21
X struct stat pdirstat;
X
X if (stat(prefdir,&pdirstat))
X {
X RCSfilename=sub2filename;
X }
X else
X {
X#ifdef AMIGA
X if (pdirstat.st_type > 0)
X#else
X if ((pdirstat.st_mode & S_IFMT) != S_IFREG)
X#endif
X {
X RCSfilename = sub1filename;
X }
X else
X {
X RCSfilename = sub2filename;
X }
X }
X@
X
X
X4.8.2.4
Xlog
X@Changed file path handling to deal with Amiga file path sematics.
X@
Xtext
X@d2 1
Xa2 1
X * RCS file name handling
Xd6 1
Xa6 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.3 89/10/15 18:27:52 rsbx Exp $ Purdue CS";
Xd9 4
Xa12 4
X * creation and deletion of semaphorefile,
X * creation of temporary filenames and cleanup()
X * pairing of RCS file names and working file names.
X * Testprogram: define PAIRTEST
Xa44 3
X * Revision 4.8.2.3 89/10/15 18:27:52 rsbx
X * More changes to make Amiga port work.
X *
Xd171 1
Xa171 1
X "c", " * ", /* C */
Xd173 5
Xa177 5
X "e", "# ", /* efl */
X "f", "c ", /* fortran */
X "h", " * ", /* C-header */
X "l", " * ", /* lex NOTE: conflict between lex and franzlisp*/
X "mac", "; ", /* macro vms or dec-20 or pdp-11 macro */
Xd181 1
Xa181 1
X "p", " * ", /* pascal */
Xd183 2
Xa184 2
X "r", "# ", /* ratfor */
X "red", "% ", /* psl/rlisp */
Xd187 1
Xa187 1
X "s", "! ", /* assembler */
Xd190 1
Xa190 1
X "s", "| ", /* assembler */
Xd193 1
Xa193 1
X "s", "/ ", /* assembler */
Xd196 1
Xa196 1
X "s", "# ", /* assembler */
Xa197 4
X#ifdef AMIGA
X "asm", "* ", /* assembler */
X "i", "* ", /* assembler include */
X#endif
Xd199 6
Xa204 6
X "sh", "# ", /* shell */
X "sl", "% ", /* psl */
X "red", "% ", /* psl/rlisp */
X "cl", ";;; ", /* common lisp */
X "ml", "; ", /* mocklisp */
X "el", "; ", /* gnulisp */
Xd206 5
Xa210 5
X "y", " * ", /* yacc */
X "ye", " * ", /* yacc-efl */
X "yr", " * ", /* yacc-ratfor */
X "", "# ", /* default for empty suffix */
X nil, "" /* default for unknown suffix; must always be last */
Xd227 2
Xa228 2
X if (ferror(fptr) || (fclose(fptr)==EOF))
X faterror("File read or write error; file system full?");
Xd242 2
Xa243 2
X register char * tp, *sp, *lp;
X int fdesc;
Xd245 3
Xa247 1
X sp=RCSname;
Xa248 17
X if (lp = index(sp,':')) /* volume: ? */
X {
X if (tp = rindex(lp,'/')) /* volume:path/ ? */
X {
X lp = tp;
X }
X }
X else
X {
X lp = rindex(sp,'/');
X }
X#else
X lp = rindex(sp,'/');
X#endif
X
X if (lp==0) {
X#ifdef AMIGA
Xd251 2
Xa252 2
X semafilename[0]='.'; semafilename[1]='/';
X tp= &semafilename[2];
Xd254 10
Xa263 10
X } else {
X /* copy path */
X tp=semafilename;
X do *tp++ = *sp++; while (sp<=lp);
X }
X /*now insert `,' and append file name */
X *tp++ = ',';
X lp = rindex(sp, RCSSEP);
X while (sp<lp) *tp++ = *sp++;
X *tp++ = ','; *tp = '\0'; /* will be the same length as RCSname*/
Xd270 14
Xa283 14
X madesema = false;
X if (access(semafilename, 0) == 0) {
X error("RCS file %s is in use",RCSname);
X return false;
X }
X if (makesema) {
X if ((fdesc=creat(semafilename, 000)) == -1) {
X error("Can't create semaphore file for RCS file %s",RCSname);
X return false;
X }
X VOID close(fdesc);
X madesema=true;
X }
X return true;
Xd292 7
Xa298 7
X if (madesema) {
X madesema=false;
X if (unlink(semafilename) == -1) {
X error("Can't find semaphore file %s",semafilename);
X }
X }
X}
Xd312 1
Xa312 1
X register int i;
Xd314 7
Xa320 7
X if (finptr!=NULL) VOID fclose(finptr);
X if (frewrite!=NULL) VOID fclose(frewrite);
X for (i=0; i<freefilename; i++) {
X if (tfnames[i][0]!='\0') VOID unlink(tfnames[i]);
X }
X InitCleanup();
X rmsema();
Xd335 3
Xa337 3
X register char * lastslash, *tp;
X if ((tp=tfnames[freefilename])==nil)
X tp=tfnames[freefilename] = talloc(NCPPN);
Xd344 2
Xa345 2
X while (fullpath<=lastslash) *tp++ = *fullpath++;
X }
Xd347 4
Xa350 4
X if (fullpath!=nil && (lastslash=rindex(fullpath,'/'))!=0) {
X /* copy path */
X while (fullpath<=lastslash) *tp++ = *fullpath++;
X }
Xd352 2
Xa353 2
X while (*tp++ = *filename++);
X return (mktemp(tfnames[freefilename++]));
Xd366 5
Xa370 5
X r = sp;
X while (*sp) {
X if (*sp++ == c) r=sp;
X }
X return r;
Xa375 7
X#ifdef AMIGA
Xchar * fnamepart(char *sp)
X/*
X * Function: Finds the filename part of a path.
X */
X {
X char *p1;
Xa376 23
X if (p1 = bindex(sp,':')) /* volume: ? */
X {
X return bindex(p1, '/');
X }
X else
X {
X return bindex(sp,'/');
X }
X
X }
X#else
Xchar * fnamepart(char *sp)
X/*
X * Function: Finds the filename part of a path.
X */
X {
X return bindex(sp, '/');
X }
X#endif
X
X
X
X
Xd380 1
Xa380 1
X register int i;
Xd382 2
Xa383 2
X Head=Dbranch=nil; AccessList=nil; Symbols=nil; Locks=nil;
X StrictLocks=STRICT_LOCKING;
Xd385 14
Xa398 14
X /* guess the comment leader from the suffix*/
X Suffix=bindex(workfilename, '.');
X if (Suffix==workfilename) Suffix= ""; /* empty suffix; will get default*/
X for (i=0;;i++) {
X if (comtable[i].suffix==nil) {
X Comment=comtable[i].comlead; /*default*/
X break;
X } elsif (strcmp(Suffix,comtable[i].suffix)==0) {
X Comment=comtable[i].comlead; /*default*/
X break;
X }
X }
X Lexinit(); /* Note: if finptr==NULL, reads nothing; only initializes*/
X}
Xd410 2
Xa411 2
X register char * * next, * match;
X register int count;
Xd413 10
Xa422 10
X for (next = argv, count = argc; count>0; next++,count--) {
X if ((*next != nil) && strcmp(fnamepart(*next),fname)==0) {
X /* fnamepart finds the beginning of the file name stem */
X match= *next;
X *next=nil;
X return match;
X }
X }
X return fname;
X}
Xd450 4
Xa453 4
X register char * sp, * tp;
X char * lastsep, * purefname, * pureRCSname;
X int opened, returncode;
X char * RCS1;
Xd456 1
Xa456 1
X if (*argv == nil) return 0; /* already paired filename */
Xd462 1
Xa462 1
X InitCleanup();
Xd464 38
Xa501 38
X /* first check suffix to see whether it is an RCS file or not */
X purefname=fnamepart(*argv); /* skip path */
X lastsep=rindex(purefname, RCSSEP);
X if (lastsep!= 0 && *(lastsep+1)==RCSSUF && *(lastsep+2)=='\0') {
X /* RCS file name given*/
X RCS1=(*argv); pureRCSname=purefname;
X /* derive workfilename*/
X sp = purefname; tp=tempfilename;
X while (sp<lastsep) *tp++ = *sp++; *tp='\0';
X /* try to find workfile name among arguments */
X workfilename=findpairfile(argc-1,argv+1,tempfilename);
X if (strlen(pureRCSname)>NCPFN) {
X error("RCS file name %s too long",RCS1);
X return 0;
X }
X } else {
X /* working file given; now try to find RCS file */
X workfilename= *argv;
X /* derive RCS file name*/
X sp=purefname; tp=tempfilename;
X while (*tp++ = *sp++);
X *(tp-1)=RCSSEP; *tp++=RCSSUF; *tp='\0';
X /* Try to find RCS file name among arguments*/
X RCS1=findpairfile(argc-1,argv+1,tempfilename);
X pureRCSname=fnamepart(RCS1);
X if (strlen(pureRCSname)>NCPFN) {
X error("working file name %s too long",workfilename);
X return 0;
X }
X }
X /* now we have a (tentative) RCS filename in RCS1 and workfilename */
X /* First, get status of workfilename */
X haveworkstat=stat(workfilename, &workstat);
X#ifdef TODO
X if ((haveworkstat==0) && ((workstat.st_mode & S_IFDIR) == S_IFDIR)) {
X diagnose("Directory %s ignored",workfilename);
X return 0;
X }
Xd503 20
Xa522 20
X /* Second, try to find the right RCS file */
X if (pureRCSname!=RCS1) {
X /* a path for RCSfile is given; single RCS file to look for */
X finptr=fopen(RCSfilename=RCS1, "r");
X if (finptr!=NULL) {
X returncode=1;
X } else { /* could not open */
X if (access(RCSfilename,0)==0) {
X error("Can't open existing %s", RCSfilename);
X return 0;
X }
X if (mustread) {
X error("Can't find %s", RCSfilename);
X return 0;
X } else {
X /* initialize if not mustread */
X returncode = -1;
X }
X }
X } else {
Xd538 1
Xa538 1
X opened=(
Xd542 5
Xa546 5
X if (opened) {
X /* open succeeded */
X returncode=1;
X } else {
X /* open failed; may be read protected */
Xd549 4
Xa552 4
X error("Can't open existing %s",RCSfilename);
X return 0;
X }
X if (mustread) {
Xd554 3
Xa556 3
X return 0;
X } else {
X /* initialize new file. Put into ./RCS if possible, strip off suffix*/
Xd559 2
Xa560 1
X if (stat(prefdir,&pdirstat)) {
Xd562 3
Xa564 1
X } else {
Xd566 1
Xa566 1
X if (pdirstat.st_type > 0) {
Xd568 1
Xa568 1
X if ((pdirstat.st_mode & S_IFMT) != S_IFREG) {
Xd570 1
Xd572 3
Xa574 1
X } else {
Xd576 1
Xd578 4
Xa581 5
X }
X returncode= -1;
X }
X }
X }
Xd583 7
Xa589 7
X if (returncode == 1) { /* RCS file open */
X#ifdef TODO
X haveRCSstat=fstat(fileno(finptr),&RCSstat);
X if ((haveRCSstat== 0) && ((RCSstat.st_mode & S_IFDIR) == S_IFDIR)) {
X diagnose("Directory %s ignored",RCSfilename);
X return 0;
X }
Xd591 5
Xa595 5
X Lexinit(); getadmin();
X } else { /* returncode == -1; RCS file nonexisting */
X haveRCSstat = -1;
X InitAdmin();
X };
Xd597 5
Xa601 5
X if (tostdout&&
X !(RCS1==tempfilename||workfilename==tempfilename))
X /*The last term determines whether a pair of */
X /* file names was given in the argument list */
X warn("Option -p is set; ignoring output file %s",workfilename);
Xd603 1
Xa603 1
X return returncode;
Xd613 2
Xa614 2
X static char namebuf[NCPPN];
X static int pathlength;
Xd616 2
Xa617 2
X register char * realname, * lastpathchar;
X register int dotdotcounter, realpathlength;
Xd619 49
Xa667 49
X if (*RCSfilename=='/') {
X return(RCSfilename);
X } else {
X if (pathlength==0) { /*call curdir for the first time*/
X if (getwd(pathbuf)==NULL)
X faterror("Can't build current directory path");
X pathlength=strlen(pathbuf);
X if (!((pathlength==1) && (pathbuf[0]=='/'))) {
X pathbuf[pathlength++]='/';
X /* Check needed because some getwd implementations */
X /* generate "/" for the root. */
X }
X }
X /*the following must be redone since RCSfilename may change*/
X /* find how many ../ to remvove from RCSfilename */
X dotdotcounter =0;
X realname = RCSfilename;
X while( realname[0]=='.' &&
X (realname[1]=='/'||(realname[1]=='.'&&realname[2]=='/'))){
X if (realname[1]=='/') {
X /* drop leading ./ */
X realname += 2;
X } else {
X /* drop leading ../ and remember */
X dotdotcounter++;
X realname += 3;
X }
X }
X /* now remove dotdotcounter trailing directories from pathbuf*/
X lastpathchar=pathbuf + pathlength-1;
X while (dotdotcounter>0 && lastpathchar>pathbuf) {
X /* move pointer backwards over trailing directory */
X lastpathchar--;
X if (*lastpathchar=='/') {
X dotdotcounter--;
X }
X }
X if (dotdotcounter>0) {
X error("Can't generate full path name for RCS file");
X return RCSfilename;
X } else {
X /* build full path name */
X realpathlength=lastpathchar-pathbuf+1;
X VOID strncpy(namebuf,pathbuf,realpathlength);
X VOID strcpy(&namebuf[realpathlength],realname);
X return(namebuf);
X }
X }
X}
Xd677 5
Xa681 5
X char pathname[NCPPN];
X register char * tp, *sp, *lp;
X lp = rindex(filename,'/');
X if (lp==0) {
X /* check current directory */
Xd683 1
Xa683 1
X return true;
Xd685 6
Xa690 6
X if (access(".",2)==0)
X return true;
X else {
X error("Current directory not writable");
X return false;
X }
Xd692 12
Xa703 12
X }
X /* copy path */
X sp=filename;
X tp=pathname;
X do *tp++ = *sp++; while (sp<=lp);
X *tp='\0';
X if (access(pathname,2)==0)
X return true;
X else {
X error("Directory %s not writable", pathname);
X return false;
X }
Xd718 3
Xa720 3
X /* no harm done if file "to" does not exist */
X if (link(from,to)<0) return -1;
X return(unlink(from));
Xd807 4
Xa810 4
X FILE *file;
X struct stat d, dd;
X char buf[2]; /* to NUL-terminate dir.d_name */
X struct direct dir;
Xd812 3
Xa814 3
X int rdev, rino;
X int off;
X register i,j;
Xd816 38
Xa853 38
X name[off= 0] = '/';
X name[1] = '\0';
X buf[0] = '\0';
X if (stat("/", &d)<0) return NULL;
X rdev = d.st_dev;
X rino = d.st_ino;
X for (;;) {
X if (stat(dot, &d)<0) return NULL;
X if (d.st_ino==rino && d.st_dev==rdev) {
X if (name[off] == '/') name[off] = '\0';
X chdir(name); /*change back to current directory*/
X return name;
X }
X if ((file = fopen(dotdot,"r")) == NULL) return NULL;
X if (fstat(fileno(file), &dd)<0) goto fail;
X chdir(dotdot);
X if(d.st_dev == dd.st_dev) {
X if(d.st_ino == dd.st_ino) {
X if (name[off] == '/') name[off] = '\0';
X chdir(name); /*change back to current directory*/
X VOID fclose(file);
X return name;
X }
X do {
X if (fread((char *)&dir, sizeof(dir), 1, file) !=1)
X goto fail;
X } while (dir.d_ino != d.st_ino);
X }
X else do {
X if(fread((char *)&dir, sizeof(dir), 1, file) != 1) {
X goto fail;
X }
X if (dir.d_ino == 0)
X dd.st_ino = d.st_ino + 1;
X else if (stat(dir.d_name, &dd) < 0)
X goto fail;
X } while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev);
X VOID fclose(file);
Xd855 10
Xa864 10
X /* concatenate file name */
X i = -1;
X while (dir.d_name[++i] != 0);
X for(j=off+1; j>0; --j)
X name[j+i+1] = name[j];
X off=i+off+1;
X name[i+1] = '/';
X for(--i; i>=0; --i)
X name[i+1] = dir.d_name[i];
X } /* end for */
Xd867 1
Xa867 1
X return NULL;
Xd883 4
Xa886 4
X int result;
X int initflag,tostdout;
X quietflag=tostdout=initflag=false;
X cmdid="pair";
Xd888 2
Xa889 2
X while(--argc, ++argv, argc>=1 && ((*argv)[0] == '-')) {
X switch ((*argv)[1]) {
Xd891 10
Xa900 10
X case 'p': tostdout=true;
X break;
X case 'i': initflag=true;
X break;
X case 'q': quietflag=true;
X break;
X default: error("unknown option: %s", *argv);
X break;
X }
X }
Xd902 9
Xa910 9
X do {
X RCSfilename=workfilename=nil;
X result=pairfilenames(argc,argv,!initflag,tostdout);
X if (result!=0) {
X diagnose("RCSfile: %s; working file: %s",RCSfilename,workfilename);
X diagnose("Full RCS file name: %s", getfullRCSname());
X }
X switch (result) {
X case 0: continue; /* already paired file */
Xd912 7
Xa918 7
X case 1: if (initflag) {
X error("RCS file %s exists already",RCSfilename);
X } else {
X diagnose("RCS file %s exists",RCSfilename);
X }
X VOID fclose(finptr);
X break;
Xd920 3
Xa922 3
X case -1:diagnose("RCS file does not exist");
X break;
X }
Xd924 1
Xa924 1
X } while (++argv, --argc>=1);
X@
X
X
X4.8.2.5
Xlog
X@Removed some debugging code.
X@
Xtext
X@d6 1
Xa6 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.4 89/10/16 19:07:19 rsbx Exp $ Purdue CS";
Xa44 3
X * Revision 4.8.2.4 89/10/16 19:07:19 rsbx
X * Changed file path handling to deal with Amiga file path sematics.
X *
Xd286 5
X@
X
X
X4.8.2.6
Xlog
X@Fix to fnamepart().
X@
Xtext
X@d6 1
Xa6 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.5 89/10/16 23:54:04 rsbx Exp $ Purdue CS";
Xa44 3
X * Revision 4.8.2.5 89/10/16 23:54:04 rsbx
X * Removed some debugging code.
X *
Xd404 1
Xa404 1
X if (p1 = strchr(sp,':')) /* volume: ? */
Xa405 1
X p1++;
X@
X
X
X4.8.2.7
Xlog
X@getfullRCSname() fixed up.
X@
Xtext
X@a152 3
X#ifdef AMIGA
Xchar * getfullRCSname();
X#endif
Xa654 1
X#ifndef AMIGA
Xa715 1
X#endif
Xd770 71
X@
X
X
X4.8.2.8
Xlog
X@mktemp() changed to use hex digits instead of decimal digits in temp
Xfile name.
X@
Xtext
X@d6 1
Xa6 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.7 89/10/17 18:38:55 rsbx Exp $ Purdue CS";
Xa44 3
X * Revision 4.8.2.7 89/10/17 18:38:55 rsbx
X * getfullRCSname() fixed up.
X *
Xd912 5
Xa916 1
Xstatic char *hex = "0123456789abcdef";
Xa917 5
Xchar *mktemp(char *template)
X {
X char *cp;
X unsigned long val;
X
Xa920 1
X {
Xd922 3
Xa924 7
X *cp = hex[val%16];
X val /= 16;
X }
X else
X {
X if (*cp != '.')
X {
Xa925 2
X }
X }
Xd927 1
Xa927 2
X if (*++cp != 0)
X {
Xd929 2
Xa930 4
X while (access(template, 0) == 0)
X {
X if (*cp == 'Z')
X {
Xd933 1
Xa933 1
X }
Xa934 1
X }
Xd936 1
Xa936 2
X else
X {
Xa937 1
X {
Xd939 1
Xa939 2
X }
X }
Xd941 1
Xa941 1
X }
X@
X
X
X4.8.2.9
Xlog
X@Previous changes to mktemp() had syntax errors.
X@
Xtext
X@d6 1
Xa6 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.8 89/10/30 13:44:29 rsbx Exp $ Purdue CS";
Xa44 4
X * Revision 4.8.2.8 89/10/30 13:44:29 rsbx
X * mktemp() changed to use hex digits instead of decimal digits in temp
X * file name.
X *
Xd926 1
Xa926 2
X if (*--cp == 'X')
X {
Xd929 4
Xa932 2
X }
X else
Xd934 1
Xa934 4
X if (*cp != '.')
X {
X break;
X }
X@
X
X
X4.8.2.10
Xlog
X@Changes to make the delete bit to track the write bit. Made protection
Xbit manipulation less insane.
X@
Xtext
X@d6 1
Xa6 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.9 89/10/30 13:53:10 rsbx Exp $ Purdue CS";
Xa44 3
X * Revision 4.8.2.9 89/10/30 13:53:10 rsbx
X * Previous changes to mktemp() had syntax errors.
X *
Xa641 1
X haveRCSstat=stat(RCSfilename,&RCSstat);
Xd643 1
X@
X
X
X4.8.2.11
Xlog
X@Added support for RCS_link files to be used as a poor O/S's symbolic link.
X@
Xtext
X@d6 1
Xa6 1
X rcsid[]= "$Id: rcsfnms.c,v 4.8.2.10 89/11/01 14:43:14 rsbx Exp $ Purdue CS";
Xa44 4
X * Revision 4.8.2.10 89/11/01 14:43:14 rsbx
X * Changes to make the delete bit to track the write bit. Made protection
X * bit manipulation less insane.
X *
Xa176 3
X#ifdef LINK
Xchar sub3filename [NCPPN]; /* used for files path/RCS/file.sfx,v */
X#endif /* LINK */
Xa521 3
X#ifdef LINK
X char prefdir2[NCPPN];
X#endif /* LINK */
Xa592 13
X#ifdef LINK
X FILE *symbolic_link_file = NULL;
X sub3filename[0]='\0';
X if ( access( "RCS_link", 0 ) == 0 )
X symbolic_link_file = fopen( "RCS_link", "r" );
X if ( symbolic_link_file ){
X int sl;
X fgets( sub3filename, NCPPN, symbolic_link_file );
X fclose( symbolic_link_file );
X sl = strlen(sub3filename);
X sub3filename[sl?sl-1:0] = '\0';
X }
X#endif /* LINK */
Xa601 5
X#ifdef LINK
X prefdir2[0] = '\0';
X if ( sub3filename[0] )
X VOID strcpy(prefdir2,sub3filename); /* preferred directory for RCS file*/
X#endif /* LINK */
Xd603 1
Xa603 5
X VOID strcat(sub1filename,RCS1);
X VOID strcat(sub2filename,RCS1);
X#ifdef LINK
X VOID strcat(sub3filename,RCS1);
X#endif /* LINK */
Xa604 1
X
Xd607 1
Xa607 6
X#ifdef LINK
X ((finptr=fopen(RCSfilename=sub2filename, "r"))!=NULL) ||
X (sub3filename[0] && ((finptr=fopen(RCSfilename=sub3filename, "r"))!=NULL)));
X#else
X ((finptr=fopen(RCSfilename=sub2filename, "r"))!=NULL) );
X#endif /* LINK */
Xa614 4
X#ifdef LINK
X (access(RCSfilename=sub2filename,0)==0) ||
X (sub3filename[0] && (access(RCSfilename=sub3filename,0)==0))){
X#else
Xa615 1
X#endif /* LINK */
Xa619 6
X#ifdef LINK
X if ( sub3filename[0] )
X error("Can't find %s, %s nor %s",sub1filename,sub2filename,sub3filename);
X else
X error("Can't find %s nor %s",sub1filename,sub2filename);
X#else
Xa620 1
X#endif /* LINK */
Xa625 19
X#ifdef LINK
X#ifdef AMIGA
X if (!stat(prefdir, &pdirstat) && (pdirstat.st_type > 0)) {
X#else
X if (!stat(prefdir, &pdirstat) && ((pdirstat.st_mode & S_IFMT) != S_IFREG)) {
X#endif
X RCSfilename = sub1filename;
X } else {
X#ifdef AMIGA
X if (!stat(prefdir2, &pdirstat) && (pdirstat.st_type > 0)) {
X#else
X if (!stat(prefdir2, &pdirstat) && ((pdirstat.st_mode & S_IFMT) != S_IFREG)) {
X#endif
X RCSfilename = sub3filename;
X } else {
X RCSfilename = sub2filename;
X }
X }
X#else
Xa638 1
X#endif /* LINK */
X@
X
X
X4.8.1.1
Xlog
X@Start of cbmvax RCS source branch.
X@
Xtext
X@a45 3
X * checked in with -k by rsbx at 89.08.10.16.20.00.
X *
X * Revision 4.8 89/05/01 15:09:41 narten
X@
SHAR_EOF
echo "End of archive 9 (of 14)"
# if you want to concatenate archives, remove anything after this line
exit